Analysis of the Pike Finance Exploit

5 min read

Learn how Pike Finance was exploited, resulting in a loss of assets worth $1.65 million.

TL;DR#

On April 30, 2024, Pike Finance was exploited across the Ethereum Mainnet, Optimism, and Arbitrum chains due to a smart contract vulnerability, which collectively resulted in a loss of over 479 ETH, 99,970 ARB, and 64,126 OP, worth approximately $1.65 million.

Introduction to Pike Finance#

Pike is a universal liquidity market optimized for native assets.

Vulnerability Assessment#

The root cause of the exploit is a misalignment in the storage layout of upgradeable smart contracts due to the introduction of a new dependency. This misalignment resulted in situations that allowed the attacker to bypass owner permissions.

Incident Analysis#

On April 26, 2024, Pike Finance was initially exploited across multiple chains, including Ethereum, Arbitrum, and Optimism networks, resulting in a loss of assets worth approximately 299,127 USDC. The attack was possible due to a forged CCTP message.

To reduce the extent of this attack, the team had to pause the protocol, and the affected contracts were upgraded with the inclusion of an additional dependency within their smart contracts.

This inclusion of the new dependency altered the storage layout of their upgradeable contracts, which caused misalignment of the variables in their new contracts.

In particular, the position of the `initialized` variable was misaligned, due to which the position occupied by this variable was taken over by some other variables, causing misalignment in the storage mapping.

As the `initialized` variable was no longer as accessible as it should be, it caused the contract to behave as if it were uninitialized.

The attacker then executed the initialize function after adding their address to the `_isActive` variable of the contract.

function initialize(address _console, address _rng, address _vault, address _gameProvider, uint16 _minPos, uint16 _maxPos) public nonPayable {
  require(msg.data.length - 4 >= 192);
  v0 = v1 = !stor_b_2_2;
  if (!stor_b_2_2) {
    v0 = v2 = stor_b_1_1 < 1;
  }
  if (!v0) {
    v0 = v3 = !this.code.size;
    if (!bool(this.code.size)) {
      v0 = 1 == stor_b_1_1;
    }
  }
  require(v0, Error("Initializable: contract is already initialized"));
  stor_b_1_1 = 1;
  if (!stor_b_2_2) {
    stor_b_2_2 = 1;
  }
  _gateway = _console;
  owner_2_0_19 = _rng;
  _endpoint = _vault;
  stor_4_0_19 = _gameProvider;
  _isActive =
    0x1 |
    (bytes31(msg.sender << 40) |
      (0xffffffffffffff0000000000000000000000000000000000000000ffffffff00 &
        ((_maxPos << 24) |
          ((0xffffffffffffffffffffffffffffffffffffffffffffffffffffff0000ffffff & (_minPos << 8)) | (_isActive & 0xffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff)))));
  _nativeAsset = 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee;
  if (!stor_b_2_2) {
    stor_b_2_2 = 0;
    emit Initialized(1);
  }
}

Four days after their original exploit, the exploiter was able to leverage this condition to further upgrade the affected contracts, thereby bypassing admin access to withdraw the funds held in these contracts.

The attack transaction on the Ethereum Mainnet resulted in a loss of 479.39 ETH, which was worth approximately $1,443,114. On the Optimism chain, the attack resulted in a loss of 64,126 OP, which were worth approximately $150,458, while on the Arbitrum chain, the attack resulted in a loss of 99,970 ARB tokens, which were worth approximately $102,269.

Aftermath#

The team acknowledged the occurrence of the exploit and stated that they are continuing to work on their investigation. In hopes of recovering the stolen assets, they announced a bug bounty reward of 20% for the attacker. They also stated that they would be sharing a post-mortem report and plans to make the affected users whole.

The team also published a detailed post-mortem report of the incident, which states that the Pike Beta version is officially sunset with no plans to re-enable the functionality of the protocol in its current state.

They further highlight their plans to continue investigating and taking legal measures to trace the stolen funds and hackers, set up an insurance pool, and execute a restitution plan for Pike users, among many other precautions. 

Solution#

To address the exploit in Pike Finance and ensure the security of upgradeable smart contracts, it is crucial to maintain the consistency of the storage layout across all contract versions. Developers must strictly adhere to appending new state variables at the end of the contract and avoid deleting or rearranging existing ones. This approach prevents storage collisions, where changes in variable order could lead to critical application errors.

Adopting a namespaced storage layout, as recommended by ERC-7201, can significantly enhance the management of storage structures. This practice involves implementing namespaces for storage variables and isolating storage areas to minimize the risk of unintended interactions during contract upgrades. It is particularly beneficial when modifying base contracts or adjusting the inheritance hierarchy.

In the realm of proxy patterns, ensuring a clear separation between the proxy contract that handles all user interactions and the implementation contract containing the logic is vital. This separation helps in avoiding unintended interactions between user calls and the proxy logic. Clear and non-conflicting function selectors are crucial, as they determine which function in the implementation contract is called. It's also important to avoid shadowing important administrative functions in the proxy contract with new implementations.

Incorporating storage gaps into smart contracts is another effective solution. These are unused storage spaces intentionally left in the contracts to accommodate future variables. This flexible approach allows the addition of new variables without disturbing the existing storage layout, providing a buffer against potential misalignments due to upgrades.

Regular security audits and comprehensive testing are fundamental to maintaining the integrity of smart contracts, particularly those that are upgradeable. The quick succession of attacks on Pike Finance, separated by just four days, suggests that the team likely did not have sufficient time to conduct thorough audits or chose not to invest in more rigorous testing within this tight timeframe. This oversight highlights the need for engaging professional auditors and implementing a robust testing framework that includes unit, integration, and simulation tests. Simulation tests are particularly important as they mimic potential upgrade scenarios to detect unforeseen issues.

Even with robust security measures in place, completely eliminating the possibility of vulnerabilities being exploited remains a challenge. In these instances, partnering with Neptune Mutual is essential. By establishing a dedicated cover pool with Neptune Mutual, the negative impact of events like the Pike Finance exploit can be significantly reduced. Neptune Mutual is renowned for providing coverage for losses stemming from smart contract vulnerabilities, using parametric policies tailored specifically for these types of risks.

Working with Neptune Mutual streamlines the recovery process for users by minimizing the need for extensive proof of loss documentation. Once an incident is verified and resolved through our comprehensive incident resolution protocol, we swiftly shift our focus to providing prompt compensation and financial support to those affected. This method ensures quick relief for users impacted by such security incidents.

Our coverage through our marketplace spans multiple key blockchain networks, including EthereumArbitrum, and the BNB chain, offering broad support to a varied demographic of DeFi users. This broad coverage enhances our capability to protect against diverse vulnerabilities, thereby bolstering the overall security of our extensive client base.

Reference Source BlockSec

By

Tags